package com.wjh.anyview.service.impl;

import com.alibaba.fastjson.JSON;
import com.wjh.anyview.dao.ExamMapper;
import com.wjh.anyview.entity.bo.examServiceBo.TimeConflictBo;
import com.wjh.anyview.entity.dto.CommonResult;
import com.wjh.anyview.entity.po.Exam;
import com.wjh.anyview.service.ExamService;
import com.wjh.anyview.service.constant.ExamStatusConstant;
import com.wjh.anyview.service.constant.StringConstant;
import com.wjh.anyview.util.TimeUtil;
import com.wjh.anyview.websocket.entity.bo.TopicMessage;
import com.wjh.anyview.websocket.entity.po.PreExamMessage;
import com.wjh.anyview.websocket.server.WebSocketResource;
import com.wjh.anyview.websocket.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 消息生产者，注入redisTemplate,用convertAndSend发送消息
 *
 * @author wjh
 * @date 2021/10/11 21:02
 * @Package com.example.demo.service
 */
@Service
@Slf4j
public class PublisherService {
    @Resource
    private ExamMapper examMapper;

    @Resource
    private ExamService examService;

    private final StringRedisTemplate redisTemplate;

    @Autowired
    public PublisherService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public CommonResult<String> sendMessage(String name) {
        try {
            redisTemplate.convertAndSend("TOPIC_USERNAME", name);
            return CommonResult.operateSuccess("消息发送成功");

        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.operateFailWithMessage("消息发送失败");
        }
    }

    public CommonResult<String> sendBeginExamMessage(String message, String numList, Long examId) {
        //查询本次考试信息
        Exam exam = examMapper.selectById(examId);
        //准备开始开始对象
        PreExamMessage preExamMessage = new PreExamMessage();
        preExamMessage.setExamId(examId);
        preExamMessage.setStartTime(exam.getStartTime());
        //添加进PRE_EXAM_MESSAGE_LIST集合
        WebSocketResource.PRE_EXAM_MESSAGE_LIST.add(preExamMessage);
        //PRE_EXAM_MESSAGE_LIST转json存redis
        String json = JSON.toJSONString(WebSocketResource.PRE_EXAM_MESSAGE_LIST);
        //把ONLINE_EXAM_MESSAGE_LIST的json字符串形式添加进redis
        redisTemplate.opsForValue().set(WebSocketResource.PRE_EXAM_LIST, json);

        //以当前毫秒时间戳作为redis中value的key
        String key = String.valueOf(System.currentTimeMillis());
        //redis中存放numList
        redisTemplate.opsForValue().set(key, numList);
        TopicMessage topicMessage = new TopicMessage();
        topicMessage.setMessage(message);
        topicMessage.setKey(key);
        try {
            //向TOPIC_USERNAME频道发送信息
            redisTemplate.convertAndSend("TOPIC_USERNAME", SecurityUtil.getTopicMessage(topicMessage));
            //返回key，在websocket中用于获取对应的websocket session
            return CommonResult.operateSuccess(key);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.operateFailWithMessage("服务器异常，暂时不能开始考试！");
        }
    }

    public CommonResult<String> delayExam(Long examId, Integer delayTime) {
        Exam exam = examMapper.selectById(examId);
        //开始不再进行
        if (!exam.getStatus().equals(ExamStatusConstant.IN_PROGRESS)) {
            return CommonResult.operateFailWithMessage("该考试不在进行状态!");
        }
        //判断延迟之后是否有考试冲突
        Exam examForBd = examMapper.selectById(examId);
        TimeConflictBo timeConflictBo = new TimeConflictBo();
        timeConflictBo.setCourseId(examId);
        //考试开始前两个小时
        timeConflictBo.setMinTime(examForBd.getStartTime() - 2 * 60 * 60);
        //考试结束后两个小时
        timeConflictBo.setMaxTime(examForBd.getEndTime() + 2 * 60 * 60);
        if (examService.judgeTimeConflict(timeConflictBo)) {
            return CommonResult.operateFailWithMessage("不能延迟该时间，会有考试冲突！");
        }

        Exam newExam = new Exam();
        newExam.setId(examId);
        newExam.setEndTime(TimeUtil.timestampAddMit(exam.getEndTime() * 1000, delayTime));
        newExam.setStatus(ExamStatusConstant.IN_PROGRESS);
        //更新结束时间
        if (examMapper.updateById(newExam) <= 0) {
            return CommonResult.operateFailWithMessage(StringConstant.SYSTEM_BUSY);
        }
        //查询需要通知的学号
        List<String> nums = examService.listNumByExamId(examId);
        String numList = nums.toString();
        //以当前毫秒时间戳作为redis中value的key
        String key = String.valueOf(System.currentTimeMillis());
        //redis中存放numList
        redisTemplate.opsForValue().set(key, numList.substring(1, numList.length() - 1));
        TopicMessage topicMessage = new TopicMessage();
        topicMessage.setMessage("考试延迟 " + delayTime + " 分钟结束！");
        topicMessage.setKey(key);

        //向频道发送信息
        redisTemplate.convertAndSend("TOPIC_EXAM", SecurityUtil.getTopicMessage(topicMessage));
        return CommonResult.operateSuccess("延迟考试成功！");
    }
}